package com.tbit.uqbike.service.business.operationsanalysis.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tbit.manager.api.dto.UserStatParam;
import com.tbit.manager.api.vo.LineChartData;
import com.tbit.manager.api.vo.PieChartData;
import com.tbit.uqbike.object.pojo.NewUserDaySta;

import com.tbit.uqbike.object.pojo.statistics.SexPieData;
import com.tbit.uqbike.service.business.operationsanalysis.UserOAService;

import com.tbit.uqbike.webmanager.dao.core.UserDao;
import com.tbit.uqbike.webmanager.dao.stat.NewUserDayStaDao;
import com.tbit.uqbike.webmanager.dao.stat.VipCardOrderDayStaDao;
import com.tbit.utils.DateTimeUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

/**
 * 用户分析Service接口实现
 *
 * @author <a href="mailto:chen.wutian@tbit.com.cn">BUGTian</a>
 * @since 2025/2/27
 */
@Service
@AllArgsConstructor
public class UserOAServiceImpl implements UserOAService {

    private final UserDao userDao;
    private final NewUserDayStaDao newUserDayStaDao;
    private final VipCardOrderDayStaDao vipCardOrderDayStaDao;

    @Override
    public Long totalUserCount(UserStatParam param) {
        return userDao.totalUserCount(param);
    }

    @Override
    public Long nameAuthUserCount(UserStatParam param) {
        return userDao.nameAuthUserCount(param);
    }

    @Override
    public Long newUserCount(UserStatParam param) {
        List<NewUserDaySta> newUserDayStaList = newUserDayStaDao.selectList(new LambdaQueryWrapper<NewUserDaySta>()
                .eq(NewUserDaySta::getAccountId, param.getAccountId())
                .between(NewUserDaySta::getNewUserDayDate, param.getStartDate(), param.getEndDate())
        );
        return newUserDayStaList.parallelStream().filter(x -> Objects.nonNull(x) && Objects.nonNull(x.getNewUserCount()))
                .mapToLong(NewUserDaySta::getNewUserCount)
                .sum();
    }

    @Override
    public Long vipUserCount(UserStatParam param) {
        return vipCardOrderDayStaDao.vipUserCount(param);
    }

    @Override
    public List<LineChartData> newUserLineChart_Day(UserStatParam param) {
        List<LineChartData> lineChartData = newUserDayStaDao.newUserLineChart_Day(param);
        fixNullData(lineChartData,param);
        return lineChartData.stream().sorted((o1, o2) -> {
            LocalDate date1 = LocalDate.parse(o1.getDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            LocalDate date2 = LocalDate.parse(o2.getDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            return date1.compareTo(date2);
        }).collect(Collectors.toList());
    }

    /**
     * 缺失的数据补0
     * @param list
     * @param param
     */
    private void fixNullData(List<LineChartData> list, UserStatParam param){
        List<String> daysStr = DateTimeUtil.findDaysStr(param.getStartDate(), param.getEndDate());
        Set<String> existDate = list.stream().map(LineChartData::getDate).collect(Collectors.toSet());
        daysStr.forEach(x -> {
            if (!existDate.contains(x)){
                list.add(new LineChartData().setDate(x).setNum(0));
            }
        });
    }

    @Override
    public List<LineChartData> newVipLineChart_Day(UserStatParam param) {
        List<LineChartData> lineChartData = vipCardOrderDayStaDao.newVipLineChart_Day(param);
        fixNullData(lineChartData,param);
        return lineChartData.stream().sorted((o1, o2) -> {
            LocalDate date1 = LocalDate.parse(o1.getDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            LocalDate date2 = LocalDate.parse(o2.getDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            return date1.compareTo(date2);
        }).collect(Collectors.toList());
    }

    @Override
    public List<PieChartData> ageDistributionPieChart(UserStatParam param) {
        List<LocalDate> dateList = userDao.getUserBirthDayList(param);
        return getAgeDistribute(dateList);
    }

    /**
     * 统计年龄段分布
     * @param dateList
     * @return
     */
    private List<PieChartData> getAgeDistribute(List<LocalDate> dateList){
        // 计数变量
        int unknown = 0;
        int lt_20 = 0;
        int bt_20_25 = 0;
        int bt_25_30 = 0;
        int bt_30_35 = 0;
        int bt_35_40 = 0;
        int bt_40_50 = 0;
        int gt_50 = 0;
        Map<String,Number> resMap = new HashMap<>();
        LocalDate now = LocalDate.now();
        for (LocalDate birthDate : dateList) {
            if (Objects.isNull(birthDate)){
                unknown ++;
                continue;
            }
            int age = getAge(birthDate, now);
            if (age <= 20){
                lt_20 ++;
            } else if (age <= 25){
                bt_20_25 ++;
            } else if (age <= 30){
                bt_25_30 ++;
            } else if (age <= 35){
                bt_30_35 ++;
            } else if (age <= 40){
                bt_35_40 ++;
            } else if (age <= 50){
                bt_40_50 ++;
            } else {
                gt_50 ++;
            }
        }
        List<PieChartData> res = new ArrayList<>();
        res.add(new PieChartData().setName("未知").setData(unknown));
        res.add(new PieChartData().setName("小于20").setData(lt_20));
        res.add(new PieChartData().setName("20-25").setData(bt_20_25));
        res.add(new PieChartData().setName("25-30").setData(bt_25_30));
        res.add(new PieChartData().setName("30-35").setData(bt_30_35));
        res.add(new PieChartData().setName("35-40").setData(bt_35_40));
        res.add(new PieChartData().setName("40-50").setData(bt_40_50));
        res.add(new PieChartData().setName("大于50").setData(gt_50));
        res.add(new PieChartData().setName("total").setData(dateList.size()));
        return res;
    }

    /**
     * 获取相差的年龄
     * @param birthDate
     * @param now
     * @return
     */
    private Integer getAge(LocalDate birthDate, LocalDate now){
        Period between = Period.between(birthDate, now);
        return between.getYears();
    }
    @Override
    public List<PieChartData> sexDistributionPieChart(UserStatParam param) {
        List<PieChartData> res = new ArrayList<>();
        Map<String, SexPieData> map = userDao.sexDistributionPieChart(param);
        for (Map.Entry<String, SexPieData> entry : map.entrySet()) {
            String key = entry.getKey();
            SexPieData value = entry.getValue();
            if (Objects.equals(key, "0")) {
                res.add(new PieChartData().setName("女").setData(value.getNum()));
            } else if (Objects.equals(key,"1")) {
                res.add(new PieChartData().setName("男").setData(value.getNum()));
            }else {
                res.add(new PieChartData().setName("未知性别").setData(value.getNum()));
            }
        }
        return res;
    }
}
